/*
 * debug_printf.h
 *  调试信息输出
 *  Created on: 2022年02月22日
 *      Author: guyadong
 */

#ifndef COMMON_SOURCE_CPP_DEBUG_PRINTF_H_
#define COMMON_SOURCE_CPP_DEBUG_PRINTF_H_

#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
/************************************************************************/
/* 是否使用MMU(memory management unit)宏定义开关                        */
/************************************************************************/
#ifndef COMMON_DBG_USE_MMU
#if HAS_MALLOC && HAS_FREE
#define COMMON_DBG_USE_MMU 1
#else
#define COMMON_DBG_USE_MMU 0
#endif
#endif

#define COM_PRINTF_DEBUG(fmt,...) if(dbg_debuglog){ com_debug_printf(fmt,##__VA_ARGS__);}

#define COM_PRINTF_DEBUG_IF(_f,fmt,...) if(_f){ com_debug_printf(fmt,##__VA_ARGS__);}

#define COM_PRINTF_DEBUG_IF_BITMATCHALL(_f,fmt,...) if((dbg_debuglog&_f)==_f){ com_debug_printf(fmt,##__VA_ARGS__);}

#define COM_PRINTF_DEBUG_IF_BITMATCH0(_f,fmt,...) if((dbg_debuglog&_f)){ com_debug_printf(fmt,##__VA_ARGS__);}

 /** 向 dbg_errbuf 输出错误日志 */
#define COM_ERR_PRINTF(fmt,...) {COM_PRINTF_DEBUG(fmt,##__VA_ARGS__);if(dbg_errbuf && dbg_errbufsz){com_debug_snprintf(dbg_errbuf,dbg_errbufsz,fmt,##__VA_ARGS__);}}

 /** 向 dbg_errbuf 输出错误日志 */
#define COM_ERR_PRINTF_IF(_f,fmt,...) {COM_PRINTF_DEBUG_IF(_f,fmt,##__VA_ARGS__);if(dbg_errbuf && dbg_errbufsz){com_debug_snprintf(dbg_errbuf,dbg_errbufsz,fmt,##__VA_ARGS__);}}

#ifdef __cplusplus
extern "C"
{
#endif

#ifdef NATIVE_VPRINTF
extern int common_dbg_vprintf(const char* fmt, va_list args);
#define COMMON_DEBUG_VPRINTF common_dbg_vprintf
#else
#define COMMON_DEBUG_VPRINTF vprintf
#endif

#ifdef NATIVE_PRINTF
extern int common_dbg_printf(const char* fmt, va_list args);
#define COMMON_DEBUG_PRINTF common_dbg_printf
#else
#define COMMON_DEBUG_PRINTF printf
#endif
/** 调试信息输出标志 */
extern uint32_t dbg_debuglog;
/** 错误信息输出缓冲区 */
extern char*  dbg_errbuf;
/** 错误信息输出缓冲区长度 */
extern size_t dbg_errbufsz;
//************************************
// 指定错误信息输出缓冲区,
// 当函数调用出错时,可从缓冲区获取错误信息,
// 如果未定义则不能获取详细错误信息
// @param    char * _errbuf 缓存区地址
// @param    size_t _errbufsz 缓存区长度
//************************************
void dbg_define_err_buf(char * _errbuf, size_t _errbufsz);
//************************************
// 是否输出调试信息(默认为0,不输出日志)
// @param    uint32_t _debuglog 标志位定义参见 DBGLOG_CFG
//************************************
void dbg_set_debuglog(uint32_t _debuglog);
//************************************
// 带时间戳和源码信息(__FILE__,__FUNCTION__, __LINE__)的格式化打印输出
// @param    char *       buf    输出缓冲区
// @param    size_t       bufsz  输出缓冲区长度
// @param    const char * file   源码文件名,__FILE__
// @param    const char * fun    函数名    ,__FUNCTION__
// @param    int          line   源码行号  ,__LINE__
// @param    const char * fmt    格式字符串,参见 vsnprintf 或 vprintf
// @param    ...                 fmt 的输入参数 
// @return   int                 调用 vsnprintf 或 vprintf 的返回值
//************************************
int _dbg_debug_vsnprintf(char* buf, size_t bufsz, const char* file, const char* fun, int line, const char* fmt, va_list args);
int _dbg_debug_snprintf(char* buf, size_t bufsz, const char* file, const char* fun, int line, const char* fmt, ...);
int _dbg_debug_vprintf_(const char* file, const char* fun, int line, const char* fmt, va_list args);
//************************************
// 带时间戳和源码信息(__FILE__,__FUNCTION__, __LINE__)的格式化打印输出
// @param    const char * file   源码文件名,__FILE__
// @param    const char * fun    函数名    ,__FUNCTION__
// @param    int          line   源码行号  ,__LINE__
// @param    const char * fmt    格式字符串,参见 vsnprintf 或 vprintf
// @param    ...                 fmt 的输入参数 
// @return   int                 调用 vsnprintf 或 vprintf 的返回值
//************************************
int _dbg_debug_printf_(const char* file, const char* fun, int line, const char* fmt, ...);
//************************************
// 带时间戳和源码信息(__FILE__,__FUNCTION__, __LINE__)的格式化打印输出
// @param    char *       buf    vsnprintf 输出缓冲区,如果为 NULL,则向控制台输出(vprintf)
// @param    size_t       bufsz  vsnprintf 输出缓冲区长度,如果为 0,则向控制台输出(vprintf)
// @param    const char * file   源码文件名,__FILE__
// @param    const char * fun    函数名    ,__FUNCTION__
// @param    int          line   源码行号  ,__LINE__
// @param    const char * fmt    格式字符串,参见 vsnprintf 或 vprintf
// @param    ...                 fmt 的输入参数 
// @return   int                 调用 vsnprintf 或 vprintf 的返回值
//************************************
int _dbg_debug_printf(char* buf, size_t bufsz, const char* file, const char* fun, int line, const char* fmt, ...);

/** 向控制台输出 */
#define com_debug_printf(fmt,...) _dbg_debug_printf_(__FILE__,__FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)

/** 向内存缓存区输出输出 */
#define com_debug_snprintf(buf,bufsz,fmt,...) _dbg_debug_snprintf(buf, bufsz, __FILE__,__FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
/************************************************************************/
/* 当有MMU(memory management unit)支持时可用                            */
/************************************************************************/
#if COMMON_DBG_USE_MMU
//************************************
// 将指定长度的字符串(包含结尾'\0')复制到新分配的内存
// @param    const char * str
// @param    size_t size 为0,则strlen 计算
// @return   char* 内存分配失败返回NULL
//************************************
char* dbg_strndump(const char* str, size_t size);
//************************************
// 基于 vsnprintf 向申请的内存格式化输出字符串
// @param     const char * fmt 格式字符串,参见 vsnprintf 或 vprintf
// @param     ...              fmt 的输入参数
// @return    char       * 格式化输出的字符串地址,内存分配失败返回 NULL
//************************************
char* dbg_buf_printf(const char* fmt, ...);
//************************************
// 基于 vsnprintf 向申请的内存格式化输出字符串
// @param     const char * fmt  格式字符串,参见 vsnprintf 或 vprintf
// @param     va_list      args fmt 的输入参数
// @return    char       * 格式化输出的字符串地址,内存分配失败返回 NULL
//************************************
char* dbg_buf_vprintf(const char* fmt, va_list args);
//************************************
// 控制台输出字符串(input)的指定范围的字符
// @param    const char * file   源码文件名,__FILE__
// @param    const char * fun    函数名    ,__FUNCTION__
// @param    int          line   源码行号  ,__LINE__
// @param    const char * msg    消息前缀
// @param    const char * input  待输出字符串
// @param    size_t       _start 输出起始偏移
// @param    size_t       _end   输出结束偏移
//************************************
void dbg_print_str(const char* file, const char* fun, int line, const char* msg, const char* input, size_t _start, size_t _end);
#endif
//************************************
#ifdef __cplusplus
}
#endif
#endif /* COMMON_SOURCE_CPP_DEBUG_PRINTF_H_ */
